import random
import string
import hashlib
import time
from django.core.cache import cache  # 使用Django缓存（建议配置Redis）

# 缓存有效期（5分钟）
VERIFY_EXPIRE = 300


class SliderVerify:
    """滑动验证核心工具：生成验证信息、校验轨迹、生成验证令牌"""

    @staticmethod
    def generate_verify():
        """生成验证ID和缺口位置，存入缓存"""
        # 生成唯一验证ID
        chars = string.ascii_letters + string.digits
        verify_id = ''.join(random.choices(chars, k=16))
        # 随机生成缺口位置（600px宽的背景图，缺口50px）
        # 缺口位置范围：50-550（确保缺口完全在背景内，且不在最边缘）
        gap_left = random.randint(50, 550)
        # 存入缓存（verify_id -> 缺口位置）
        cache_key = f"slider_verify_{verify_id}"
        cache.set(cache_key, gap_left, timeout=VERIFY_EXPIRE)
        return {
            "verify_id": verify_id,
            "bg_width": 600,  # 背景图宽度（供前端绘制）
            "gap_size": 50,  # 缺口大小（供前端绘制）
            "gap_left": gap_left  # 缺口位置（随机）
        }

    @staticmethod
    def check_track(verify_id, user_left, track_data, start_time, end_time):
        """校验滑动轨迹，通过则生成验证令牌"""
        # 1. 验证verify_id是否存在并获取缺口位置
        verify_key = f"slider_verify_{verify_id}"
        gap_left = cache.get(verify_key)
        if gap_left is None:
            return False, "验证已过期，请刷新"

        # 2. 校验滑动时间（300ms - 5000ms）
        duration = end_time - start_time
        if duration < 300 or duration > 5000:
            return False, "滑动速度异常"

        # 3. 校验轨迹连续性（至少5个点，无大幅跳变）
        if len(track_data) < 5:
            return False, "轨迹不完整"

        # 检查轨迹是否从左侧开始，向右滑动
        first_x = track_data[0]['x']
        last_x = track_data[-1]['x']

        # 轨迹应该从左向右（x值递增）
        if last_x <= first_x:
            return False, "轨迹方向异常"

        # 检查轨迹连续性（无大幅跳变）
        prev_x = track_data[0]['x']
        for p in track_data[1:]:
            delta = abs(p['x'] - prev_x)
            # 针对不同终端/缩放场景放宽阈值，同时排除明显异常的大跳动
            if delta > 60:
                return False, "轨迹异常"
            prev_x = p['x']

        # 4. 校验最终位置
        # user_left 是滑块左边缘位置，gap_left 是缺口左边缘位置
        # 两者应该对齐（滑块宽度和缺口大小都是50px）
        # 允许±15px的误差范围
        error_threshold = 20
        distance = abs(user_left - gap_left)
        if distance > error_threshold:
            return False, "轨迹异常"

        # 验证通过：生成一次性令牌（5分钟有效）
        token_str = f"{verify_id}_{time.time()}"
        verify_token = hashlib.md5(token_str.encode()).hexdigest()
        cache.set(f"slider_token_{verify_token}", True,
                  timeout=VERIFY_EXPIRE)
        # 删除已使用的验证ID（防止重复验证）
        cache.delete(verify_key)
        return True, verify_token
